package com.njtoyo.taxi.admin.service.business.geo.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njtoyo.taxi.admin.cache.PrimaryCachePutter;
import com.njtoyo.taxi.admin.library.Const;
import com.njtoyo.taxi.admin.library.common.util.CopyUtil;
import com.njtoyo.taxi.admin.library.taxi_service.TaxiService;
import com.njtoyo.taxi.admin.library.taxi_service.TaxiServiceResponse;
import com.njtoyo.taxi.admin.mapper.master.entity.GeoArea;
import com.njtoyo.taxi.admin.mapper.master.mapper.GeoAreaMapper;
import com.njtoyo.taxi.admin.rest.presenter.business.geo.AllListPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.business.area.AreaCreateWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.business.area.AreaQueryWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.business.area.AreaUpdateIsOpenWrapper;
import com.njtoyo.taxi.admin.rest.wrapper.business.area.AreaUpdateWrapper;
import com.njtoyo.taxi.admin.service.business.geo.AreaService;
import com.taxi.entity.common.RestResult;
import com.taxi.entity.common.ResultEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Objects;

@Component
@DS(Const.PRIMARY_DS)
@RequiredArgsConstructor
public class AreaServiceImpl implements AreaService {
    private final GeoAreaMapper geoAreaMapper;
    private final TaxiService taxiService;
    @Autowired
    private PrimaryCachePutter primaryCachePutter;

    @Override
    public RestResult<List<AllListPresenter>> getAll() {
        List<GeoArea> list = new LambdaQueryChainWrapper<>(geoAreaMapper)
                .select(GeoArea::getId, GeoArea::getName)
                .eq(GeoArea::getIsOpened, true)
                .list();

        List<AllListPresenter> res = CopyUtil.copyList(list, AllListPresenter.class);

        return RestResult.success(res);
    }

    @Override
    public RestResult<IPage<GeoArea>> getList(AreaQueryWrapper wrapper) {
        Page<GeoArea> page = new Page<>(wrapper.getCurrent(), wrapper.getSize());

        LambdaQueryWrapper<GeoArea> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Objects.nonNull(wrapper.getIsOpened()), GeoArea::getIsOpened, wrapper.getIsOpened())
                .like(Objects.nonNull(wrapper.getName()), GeoArea::getName, wrapper.getName())
                .like(Objects.nonNull(wrapper.getAdCode()), GeoArea::getAdCode, wrapper.getAdCode());

        IPage<GeoArea> res = geoAreaMapper.selectPage(page, queryWrapper);

        return RestResult.success(res);
    }

    @Override
    public RestResult<Boolean> update(Long id, AreaUpdateWrapper wrapper) {
        GeoArea area = geoAreaMapper.selectById(id);
        if (Objects.isNull(area)) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        if (Objects.nonNull(wrapper.getAdCode())) {
            QueryWrapper<GeoArea> otherAreaQuery = new QueryWrapper<GeoArea>()
                    .ne("id", area.getId())
                    .eq("ad_code", wrapper.getAdCode());
            List<GeoArea> otherArea = geoAreaMapper.selectList(otherAreaQuery);
            if (!otherArea.isEmpty()) {
                return RestResult.failed("地区编码已存在");
            }
        }

        Boolean res = new LambdaUpdateChainWrapper<>(geoAreaMapper)
                .eq(GeoArea::getId, id)
                .set(Objects.nonNull(wrapper.getName()), GeoArea::getName, wrapper.getName())
                .set(Objects.nonNull(wrapper.getAdCode()), GeoArea::getAdCode, wrapper.getAdCode())
                .set(Objects.nonNull(wrapper.getIsOpened()), GeoArea::getIsOpened, wrapper.getIsOpened())
                .set(GeoArea::getUpdatedAt, new Date())
                .update();

        primaryCachePutter.deleteAllArea();


        return RestResult.success(res);
    }

    @Override
    public RestResult<Boolean> updateIsOpen(AreaUpdateIsOpenWrapper wrapper) {
        Integer count = new LambdaQueryChainWrapper<>(geoAreaMapper)
                .in(GeoArea::getId, wrapper.getIds())
                .count();

        if (!count.equals(wrapper.getIds().size())) {
            return RestResult.build(ResultEnum.NOT_FOUND);
        }

        Boolean res = new LambdaUpdateChainWrapper<>(geoAreaMapper)
                .in(GeoArea::getId, wrapper.getIds())
                .set(GeoArea::getIsOpened, wrapper.getIsOpened())
                .set(GeoArea::getUpdatedAt, new Date())
                .update();

        return RestResult.success(res);
    }

    @Override
    public RestResult create(AreaCreateWrapper wrapper) {
        // 判断 adCode 不能重复
        List<GeoArea> areaList = geoAreaMapper.selectList(new QueryWrapper<GeoArea>().eq("ad_code", wrapper.getAdCode()));
        if (!areaList.isEmpty()) {
            return RestResult.failed("地区编码已存在");
        }
        GeoArea area = CopyUtil.copy(wrapper, GeoArea.class);

        geoAreaMapper.insert(area);
        primaryCachePutter.deleteAllArea();
        return RestResult.success();
    }

    @Override
    public RestResult<?> refresh() {
        TaxiServiceResponse res = taxiService.refreshRegion();
        return RestResult.success(res);
    }
}
